﻿using System;
using GeoAPI.Geometries;
using NetTopologySuite.Geometries;
using NetTopologySuite.IO;

namespace NetTopologySuite.Triangulate.QuadEdge
{
	public class QuadEdge
	{
		public static QuadEdge MakeEdge(Vertex o, Vertex d)
		{
			QuadEdge quadEdge = new QuadEdge();
			QuadEdge quadEdge2 = new QuadEdge();
			QuadEdge quadEdge3 = new QuadEdge();
			QuadEdge quadEdge4 = new QuadEdge();
			quadEdge.Rot = quadEdge2;
			quadEdge2.Rot = quadEdge3;
			quadEdge3.Rot = quadEdge4;
			quadEdge4.Rot = quadEdge;
			quadEdge.SetNext(quadEdge);
			quadEdge2.SetNext(quadEdge4);
			quadEdge3.SetNext(quadEdge3);
			quadEdge4.SetNext(quadEdge2);
			QuadEdge quadEdge5 = quadEdge;
			quadEdge5.Orig = o;
			quadEdge5.Dest = d;
			return quadEdge5;
		}

		public static QuadEdge Connect(QuadEdge a, QuadEdge b)
		{
			QuadEdge quadEdge = QuadEdge.MakeEdge(a.Dest, b.Orig);
			QuadEdge.Splice(quadEdge, a.LNext);
			QuadEdge.Splice(quadEdge.Sym, b);
			return quadEdge;
		}

		public static void Splice(QuadEdge a, QuadEdge b)
		{
			QuadEdge rot = a.ONext.Rot;
			QuadEdge rot2 = b.ONext.Rot;
			QuadEdge onext = b.ONext;
			QuadEdge onext2 = a.ONext;
			QuadEdge onext3 = rot2.ONext;
			QuadEdge onext4 = rot.ONext;
			a.SetNext(onext);
			b.SetNext(onext2);
			rot.SetNext(onext3);
			rot2.SetNext(onext4);
		}

		public static void Swap(QuadEdge e)
		{
			QuadEdge oprev = e.OPrev;
			QuadEdge oprev2 = e.Sym.OPrev;
			QuadEdge.Splice(e, oprev);
			QuadEdge.Splice(e.Sym, oprev2);
			QuadEdge.Splice(e, oprev.LNext);
			QuadEdge.Splice(e.Sym, oprev2.LNext);
			e.Orig = oprev.Dest;
			e.Dest = oprev2.Dest;
		}

		private QuadEdge()
		{
		}

		public QuadEdge GetPrimary()
		{
			if (this.Orig.Coordinate.CompareTo(this.Dest.Coordinate) <= 0)
			{
				return this;
			}
			return this.Sym;
		}

		public object Data { get; set; }

		public void Delete()
		{
			this.Rot = null;
		}

		public bool IsLive
		{
			get
			{
				return this.Rot != null;
			}
		}

		public void SetNext(QuadEdge next)
		{
			this._next = next;
		}

		internal QuadEdge Rot { get; set; }

		private QuadEdge InvRot
		{
			get
			{
				return this.Rot.Sym;
			}
		}

		internal QuadEdge Sym
		{
			get
			{
				return this.Rot.Rot;
			}
		}

		internal QuadEdge ONext
		{
			get
			{
				return this._next;
			}
		}

		internal QuadEdge OPrev
		{
			get
			{
				return this.Rot._next.Rot;
			}
		}

		internal QuadEdge DNext
		{
			get
			{
				return this.Sym.ONext.Sym;
			}
		}

		internal QuadEdge DPrev
		{
			get
			{
				return this.InvRot.ONext.InvRot;
			}
		}

		internal QuadEdge LNext
		{
			get
			{
				return this.InvRot.ONext.Rot;
			}
		}

		internal QuadEdge LPrev
		{
			get
			{
				return this._next.Sym;
			}
		}

		internal QuadEdge RNext
		{
			get
			{
				return this.Rot._next.InvRot;
			}
		}

		internal QuadEdge RPrev
		{
			get
			{
				return this.Sym.ONext;
			}
		}

		public Vertex Orig
		{
			get
			{
				return this._vertex;
			}
			internal set
			{
				this._vertex = value;
			}
		}

		public Vertex Dest
		{
			get
			{
				return this.Sym.Orig;
			}
			internal set
			{
				this.Sym.Orig = value;
			}
		}

		public double Length
		{
			get
			{
				return this.Orig.Coordinate.Distance(this.Dest.Coordinate);
			}
		}

		public bool EqualsNonOriented(QuadEdge qe)
		{
			return this.EqualsOriented(qe) || this.EqualsOriented(qe.Sym);
		}

		public bool EqualsOriented(QuadEdge qe)
		{
			return this.Orig.Coordinate.Equals2D(qe.Orig.Coordinate) && this.Dest.Coordinate.Equals2D(qe.Dest.Coordinate);
		}

		public LineSegment ToLineSegment()
		{
			return new LineSegment(this._vertex.Coordinate, this.Dest.Coordinate);
		}

		public override string ToString()
		{
			Coordinate coordinate = this._vertex.Coordinate;
			Coordinate coordinate2 = this.Dest.Coordinate;
			return WKTWriter.ToLineString(coordinate, coordinate2);
		}

		private Vertex _vertex;

		private QuadEdge _next;
	}
}
